package xyz.zhouxf.rpc.codec;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ReplayingDecoder;
import lombok.extern.slf4j.Slf4j;
import xyz.zhouxf.rpc.entity.RpcRequest;
import xyz.zhouxf.rpc.entity.RpcResponse;
import xyz.zhouxf.rpc.enumeration.CommonEnum;
import xyz.zhouxf.rpc.enumeration.PackageType;
import xyz.zhouxf.rpc.enumeration.RpcError;
import xyz.zhouxf.rpc.enumeration.SerializerCode;
import xyz.zhouxf.rpc.exception.RpcException;
import xyz.zhouxf.rpc.serializer.RpcSerializer;

import java.util.List;

/**
 * 解码器
 * @author zhouxf
 * @date 2022/8/20
 */
@Slf4j
public class CommonDecoder extends ReplayingDecoder {

    private static final int MAGIC_NUMBER = CommonEnum.MAGIC_NUMBER.getCode();

    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) {
        int magicNumber = byteBuf.readShort();
        if(magicNumber != MAGIC_NUMBER) {
            log.error("未知的协议包：{}",magicNumber);
            throw new RpcException(RpcError.UNKNOWN_PROTOCOL);
        }
        byte packageTypeCode = byteBuf.readByte();
        Class<?> packageClass;
        if(packageTypeCode == PackageType.REQUEST.getCode()) {
            packageClass = RpcRequest.class;
        } else if(packageTypeCode == PackageType.RESPONSE.getCode()) {
            packageClass = RpcResponse.class;
        } else {
            log.error("未知的数据包：{}",packageTypeCode);
            throw new RpcException(RpcError.UNKNOWN_PACKAGE);
        }
        byte serializerCode = byteBuf.readByte();
        RpcSerializer serializer = RpcSerializer.getRpcSerializer(serializerCode);
        if(serializer == null) {
            log.error("未知的反序列化器：{}",serializerCode);
            throw new RpcException(RpcError.UNKNOWN_SERIALIZER);
        }
        int length = byteBuf.readInt();
        byte[] bytes = new byte[length];
        byteBuf.readBytes(bytes);
        Object obj = serializer.deserialize(bytes,packageClass);
        System.out.println("list: " + list);
        System.out.println("obj: " + obj);
        list.add(obj);
    }
}
